React - State
Tot nu toe hebben we onze gegevens opgeslagen in een array in een variabele en gaven deze door als props (zie React - Props). Dit is een goed begin, maar wat als we bijvoorbeeld een item uit de array willen verwijderen? Met props hebben we een eenrichtingsgegevensstroom, maar met de state kunnen we privégegevens van een component bijwerken.
Bronnen
- State and Lifecycle, deze pagina legt het concept
stateenlifecyclein een React component uit.
Een nieuwe react app maken
- Zorg ervoor dat je openstaande Node.js servers afsluit met Ctrl-C.
- Vooraleer de create-react-app op te starten ga je naar de map waarin je het project wil maken. We gaan op Cloud9 een project maken met de naam react-state. En dat project plaatsen we in de root van onze workspace. Zorg er dus voor dat je in de root staat:
jefinghelbrecht:~/workspace $
In plaats van JefInghelbrecht zie je natuurlijk de naam van je eigen workspace. - Om een create-react-app te maken, voer je de volgende instructie in je terminal uit (zorg ervoor dat je de laatste versie van Node hebt geïnstalleerd, zie Een React App maken):
npx create-react-app react-state
Meer info over npx: Introducing npx: an npm package runner - Op Cloud9 moet je telkens opgeven dat je met de nieuwere versie wilt werken:
nvm use 8
- Als de installatie goed verlopen is, ga dan naar de nieuw aangemaakte map en start het project:
cd react-state
npm start - We maken onze eigen standaardtekst en kieperen de voorgeprogrammeerde code overboord. We behouden alleen:
- index.js
- index.css
- We deleten alle overige bestanden in de /src.
- In index.css plakken we de Primitive CSS van Tania Rascia. Je kan dat vervangen door je eigen CSS of door Bootstrap of om het even welk ander CSS framework.
- Verwijder de verwijzingen naar
serviceWorkerin index.js. Delete de gemarkeerde lijnen:import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(<App />, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: http://bit.ly/CRA-PWA serviceWorker.unregister();
'state' gebruiken om gegevens door te geven
State kan je beschouwen als het opslagen en wijzigen van om het even welk gegeven zonder dat het noodzakelijkerwijs in een database moet worden opgeslagen. Bijvoorbeeld items, die tijdens het shoppen aan een winkelwagentje worden toegevoegd en eventueel weer verwiijderd, vooraleer de aankoop te bevestigen.
- We beginnen met het maken van een
state-object in het bestand met de naam App.js:import React, { Component } from 'react'; class App extends Component { state = {}; } export default App; - Het
state-object bevat al de eigenschappen voor alle gegevens die we in de state willen opslagen. In ons voorbeeld is datalbums:import React, { Component } from 'react'; class App extends Component { state = { albums: [] }; } export default App; - We plaatsen de array met de albums van Jommeke in
state.albums:import React, { Component } from 'react'; class App extends Component { state = { albums: [{ 'nummer': '6', 'titel': 'Het hemelhuis', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '7', 'titel': 'De zwarte Bomma', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '8', 'titel': 'De ooievaar van Begonia', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '9', 'titel': 'De Schildpaddenschat', 'kaft': 'Softcover', 'prijs': '€ 5.22' }, { 'nummer': '10', 'titel': 'De straalvogel', 'kaft': 'Hardcover', 'prijs': '€ 8.22' }, { 'nummer': '11', 'titel': 'De Zonnemummie', 'kaft': 'Softcover', 'prijs': '€ 5.22' } ] }; } export default App; - De gegevens zitten nu in de
state. Om een album te kunnen verwijderen uit de tabel, gaan we eenremoveAlbummethode toevoegen aan deAppklasse. Om destateop te vragen halen wethis.state.albumsop met de ES6 methode, die we in React - Props gebruikt hebben. Om destatete updaten gebruiken we dethis.setState()methode. Deze methode is een ingebouwde methode van React om destatete kunnen bewerken. Je moetthis.setState()gebruiken om een array te wijzigen. Een nieuwe waarde toekennen aanthis.state.propertyzal niet weken! We zullen de array filteren gebaseerd op deindexdie we doorgeven. Tenslotte retourneren we de nieuwe gefilterde array. Voeg in App.js de volgende ES6 methode toe:import React, { Component } from 'react'; import Table from './Table'; class App extends Component { removeAlbum = index => { const { albums } = this.state; this.setState({ characters: albums.filter((character, i) => { return i !== index; }) }); } ...filtermuteert niet maar maakt een nieuwe array aan en is dus voorkeursmethode voor het wijzigen van arrays in JavaScript. Deze specifieke methode gaat na of een opgegevenindexovereenkomt met één van de indices in de array en het retourneert alle elementen van de array behalve die rij die dezelfdeindexheeft als de opgegeven index. - We gaan deze functie doorgeven aan de component en een HTML knop weergeven naast elk album die deze functie kan activeren. We geven de
removeAlbumfunctie door als een prop aan deTablecomponent:return ( <div className="container"> <Table albumData={albums} removeAlbum={this.removeAlbum} /> </div> ); - In de return hierboven gebruiken we de albums constante. In React - Props was die in de
render()methode gedefinieerd. Nu wordt die in destatevan de klasse gedefinieerd. Om die toegankelijk te maken in derender()methode moeten we naar de state verwijzen:return ( <div className="container"> <Table albumData={this.state.albums} removeAlbum={this.removeAlbum} /> </div> ) - We kopiëren de code van de
Tablecomponent die we gemaakt hebben in React - Props en plaatsen het in een bestand met de naam Table.js in de /src map:import React, { Component } from 'react'; const TableBody = props => { const rows = props.albumData.map((row, index) => { return ( <tr key={index}> <td>{row.nummer}</td> <td>{row.titel}</td> <td>{row.kaft}</td> <td>{row.prijs}</td> </tr> ); }); return <tbody>{rows}</tbody>; } class Table extends Component { render() { const {albumData} = this.props; return ( <table> <TableBody albumData={albumData} /> </table> ); } } export default Table; - Nu gaan we de
removeAlbummethode doorgeven aan hetTableBodyelement van deTablecomponent. We geven de methode door als een prop op dezelfde manier als dat we de albumgegevens hebben doorgegeven:class Table extends Component { render() { const {albumData, removeAlbum} = this.props; return ( <table> <TableBody albumData={albumData} removeAlbum = {removeAlbum} /> </table> ); } } - Nu kunnen we eindelijk die
indexgaan gebruiken die we in de methoderemoveAlbumgedefinieerd hebben. We geven dekey/indexaan deTableBodycomponent door als een parameter zodat defilterfunctie weet welk item er uit de lijst verwijderd moet worden. We maken de HTML knop met eenonClickevent en geven deindexdoor. In Table.js voegen we de volgende code toe:const TableBody = props => { const rows = props.albumData.map((row, index) => { return ( <tr key={index}> <td>{row.nummer}</td> <td>{row.titel}</td> <td>{row.kaft}</td> <td>{row.prijs}</td> <td><button onClick={() => props.removeAlbum(index)}>Delete</button></td> </tr> ); }); return <tbody>{rows}</tbody>; }Aan hetonClick-event kennen we een anonieme functie toe, die de methoderemoveAlbum()retourneert. Als we dat niet zouden doen dan zou deremoveAlbum()functie bij het inladen van de HTML automatisch uitgevoerd worden. - Dit is het resultaat:
React Table Component With State
2020-04-14 12:21:23